#ifndef EDDSA_H
#define EDDSA_H

#include <iostream>
#include <sstream>
#include <cctype>
#include <iomanip>

#include "signature_manager.h"  // 假设基类定义在此头文件
#include "GMPInt.h"
// ------------------------------
// 数据结构定义
// ------------------------------


// 十六进制字符转换工具函数
static uint8_t hex_char_to_value(char c) {
    if (c >= '0' && c <= '9') return c - '0';
    if (c >= 'a' && c <= 'f') return 10 + c - 'a';
    if (c >= 'A' && c <= 'F') return 10 + c - 'A';
    throw std::logic_error("Invalid hex character"); // 理论上不会到达这里
}


/**
 * EdDSA椭圆曲线点（压缩坐标或仿射坐标）
 * EdDSA通常使用压缩坐标（如Ed25519公钥为32字节）
 */
struct EdwardsPoint {
    GMPInt x;  // x坐标
    GMPInt y;  // y坐标
    GMPInt z;  // z坐标，用于仿射坐标系中的归一化
    GMPInt t;  // t坐标，用于仿射坐标系中的归一化

    EdwardsPoint() = default;
    EdwardsPoint(const mpz_t x, const mpz_t y, const mpz_t z=mpz_class(0).get_mpz_t(), const mpz_t t=mpz_class(0).get_mpz_t()) : x(x), y(y), z(z), t(t) {}

    std::string to_str() const {
        // 序列化四个坐标分量
        std::vector<std::string> components;
        components.reserve(4);
        
        components.push_back(x.to_str());
        components.push_back(y.to_str());
        components.push_back(z.to_str());
        components.push_back(t.to_str());

        // 用逗号连接各部分
        std::ostringstream oss;
        for (size_t i = 0; i < components.size(); ++i) {
            if (i > 0) oss << ",";
            oss << components[i];
        }
        return oss.str();
    }

    void set_by_str(const std::string& str) {
        // 分割字符串为四个部分
        std::vector<std::string> parts;
        std::istringstream iss(str);
        std::string part;
        
        while (std::getline(iss, part, ',')) {
            parts.push_back(part);
        }

        // 验证格式正确性
        if (parts.size() != 4) {
            throw std::invalid_argument("Invalid EdwardsPoint string format");
        }

        // 设置各坐标分量
        x.set_by_str(parts[0]);
        y.set_by_str(parts[1]);
        z.set_by_str(parts[2]);
        t.set_by_str(parts[3]);
    }

};


struct EdwardsCurve {
    GMPInt d;   // 曲线方程参数
    GMPInt p;   // 素数域模数
    EdwardsPoint G;  // 基点
    int byte_length;  // 字节长度
    GMPInt n;   // 基点的阶

    EdwardsCurve() = default;
    EdwardsCurve(const mpz_t d, const mpz_t p, const EdwardsPoint& G, const mpz_t n, const int byte_length) 
        : d(d), p(p), G(G),  n(n), byte_length(byte_length) {}
    
    std::string to_str(){
        std::ostringstream oss;
        // 序列化核心参数
        oss << d.to_str() << ";"
            << p.to_str() << ";"
            << G.to_str() << ";"
            << n.to_str() << ";"
            << std::to_string(byte_length);
        return oss.str();
    }

    void set_by_str(const std::string& str) {
        std::vector<std::string> parts;
        std::istringstream iss(str);
        std::string part;

        // 按分号分割主要参数
        while (std::getline(iss, part, ';')) {
            parts.push_back(part);
        }

        // 验证参数完整性
        if (parts.size() != 5) {
            throw std::invalid_argument("Invalid EllipticCurve string format");
        }

        // 解析基础参数
        d.set_by_str(parts[0]);
        p.set_by_str(parts[1]);
        // 解析基点坐标
        G.set_by_str(parts[2]);
        n.set_by_str(parts[3]); 
        byte_length = std::stoi(parts[4]);

    }
};

/**
 * EdDSA私钥（通常为随机种子或标量）
 */
struct EdDSA_privatekey {
    BYTE_VECTOR s;  // 私钥标量
    
    EdDSA_privatekey() = default;
    EdDSA_privatekey(const BYTE_VECTOR s) : s(s) {}

    void print(std::ostream& os) const {
        printf("[EdDSA_privatekey][debug] Compressed bytes: ");
        for (int i = 0;i < 32;i++) {
            printf("%02x", int(s[i]));
        }
        std::cout << std::endl;
    }

    std::string to_str() const {
        std::ostringstream oss;
        oss << std::hex << std::setfill('0');
        for (uint8_t byte : s) {
            oss << std::setw(2) << static_cast<int>(byte);
        }
        return oss.str();  // 示例输出："1a2b3c...ff"
    }

    void set_by_str(const std::string& str) {
        // 验证输入有效性
        if (str.empty()) {
            throw std::invalid_argument("Empty private key string");
        }

        BYTE_VECTOR new_s;
        new_s.reserve(str.size() / 2);

        for (size_t i = 0; i < str.size(); i += 2) {
            // 字符有效性检查
            if (!isxdigit(str[i]) || !isxdigit(str[i+1])) {
                throw std::invalid_argument("Invalid hex character at position " 
                    + std::to_string(i));
            }

            // 转换为字节
            uint8_t byte = (hex_char_to_value(str[i]) << 4)
                          | hex_char_to_value(str[i+1]);
            new_s.push_back(byte);
        }

        s = std::move(new_s);
    }


};

/**
 * EdDSA公钥（Edwards曲线上的点）
 */
struct EdDSA_publickey {
    BYTE_VECTOR a;  // 公钥点A = s * G
    
    EdDSA_publickey() = default;
    EdDSA_publickey(const BYTE_VECTOR& a) : a(a) {}

    void print(std::ostream& os) const {
        printf("[EdDSA_publickey][debug] Compressed bytes: ");
        for (int i = 0;i < 32;i++) {
            printf("%02x", int(a[i]));
        }
        std::cout << std::endl;
    }

    std::string to_str() const {
        std::ostringstream oss;
        oss << std::hex << std::setfill('0');
        for (uint8_t byte : a) {
            oss << std::setw(2) << static_cast<int>(byte);
        }
        return oss.str();  // 示例输出："1a2b3c...ff"
    }

    void set_by_str(const std::string& str) {
        // 验证输入有效性
        if (str.empty()) {
            throw std::invalid_argument("Empty private key string");
        }

        BYTE_VECTOR new_s;
        new_s.reserve(str.size() / 2);

        for (size_t i = 0; i < str.size(); i += 2) {
            // 字符有效性检查
            if (!isxdigit(str[i]) || !isxdigit(str[i+1])) {
                throw std::invalid_argument("Invalid hex character at position " 
                    + std::to_string(i));
            }

            // 转换为字节
            uint8_t byte = (hex_char_to_value(str[i]) << 4)
                          | hex_char_to_value(str[i+1]);
            new_s.push_back(byte);
        }
        a = std::move(new_s);
    }
    

};

/**
 * EdDSA公共参数（包含完整的曲线定义）
 */
struct EdDSA_publicparameter {
    EdwardsCurve curve;  // 曲线参数（含基点G、阶n等）
    bool is_valid = false;
    
    EdDSA_publicparameter() = default;
    EdDSA_publicparameter(const EdwardsCurve& curve) : curve(curve) {}


    std::string to_str(){
        return curve.to_str();
    }

    void set_by_str(const std::string& str) {
        curve.set_by_str(str);
        is_valid = true;
    }
};

/**
 * EdDSA签名结构（R为点，S为标量）
 * 注：实际编码中R可能被压缩，此处保持逻辑表示
 */
struct EdDSA_signature {
    EdwardsPoint R;  // 临时公钥点
    GMPInt S;        // 签名标量
    
    EdDSA_signature() = default;
    EdDSA_signature(const EdwardsPoint& R, const mpz_t S) : R(R), S(S) {}

    std::string to_str() const {
        // 序列化R和S，使用分号分隔两部分
        return R.to_str() + ";" + S.to_str();
    }

    void set_by_str(const std::string& str) {
        // 查找分号位置分割两部分
        size_t sep_pos = str.find(';');
        if (sep_pos == std::string::npos) {
            throw std::invalid_argument("Invalid EdDSA signature format");
        }

        // 解析R部分
        std::string r_str = str.substr(0, sep_pos);
        R.set_by_str(r_str);

        // 解析S部分
        std::string s_str = str.substr(sep_pos + 1);
        S.set_by_str(s_str);
    }
};

// ------------------------------
// EdDSA算法类声明
// ------------------------------
template<typename curve_name>
class EdDSA : public SignatureAlgorithm<
    EdDSA_privatekey, 
    EdDSA_publickey, 
    EdDSA_publicparameter, 
    EdDSA_signature
> {
public:
    // 生成公共参数（Ed25519）
    void generatepublicparameters(EdDSA_publicparameter& params) override;

    // 生成密钥对：s（私钥） -> A = s*G（公钥）
    void generateKeyPair(
        EdDSA_privatekey& privateKey,
        EdDSA_publickey& publicKey,
        EdDSA_publicparameter& publicParameters
    ) override;

    // 签名消息：使用私钥s和参数生成签名(R, S)
    EdDSA_signature sign(
        const PlainMessage& message,
        const EdDSA_privatekey& privateKey,
        const EdDSA_publicparameter& publicParameters
    ) override;

    // 验证签名：检查R + S*A 是否与消息哈希对应的点匹配
    bool verify(
        const PlainMessage& message,
        const EdDSA_publickey& publicKey,
        const EdDSA_publicparameter& publicParameters,
        const EdDSA_signature& signature
    ) override;
};

struct Ed25519_tag {};
struct Ed448_tag {};


template<typename curve_name>
struct EdDSA_type_traits {
    using algo = EdDSA<curve_name>;
    using private_key = EdDSA_privatekey;
    using public_key = EdDSA_publickey;
    using params = EdDSA_publicparameter;
    using signature = EdDSA_signature;
};

extern template class EdDSA<Ed25519_tag>;
extern template class EdDSA<Ed448_tag>;




#endif